/**
 * 游戏类
 * 	里面封装了游戏数据，DIV管理数组，游戏的操作方法
 */
import {blockFactory} from './blockFactory.js';

class Game{
	constructor(){
		//游戏数据
		this.data = [
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0,0]
		];
		//Blocks Div
		this.gameBlocks = [];
		this.nextBlocks = [];
		//游戏容器 DOM
		this.gameBox = '';
		this.nextBox = '';
		this.scoreBox = '';
		this.timeBox = '';
		this.statusBox = '';
		//正在操作的方块
		this.cur = '';
		//下一个方块
		this.next = '';
		//游戏得分
		this.score = 0;
	}

	/**
	 * 初始化游戏容器中的盒子--填充方块
	 * @param  {Object} container DOM容器
	 * @param  {Array} data      存放游戏数据的数组
	 * @param  {Array} blocks    存放Div盒子的数组
	 */
	initBlocks(container, data, blocks){
		for(let i=0; i<data.length; i++){
			let newBlocks = [];//新的一行方块
			for(let j=0; j<data[0].length; j++){
				let block = document.createElement('div');
				block.className = 'none';
				block.style.top = (30 * i) + 'px';
				block.style.left = (30 * j) + 'px';
				newBlocks.push(block);
				container.appendChild(block);
			}
			blocks.push(newBlocks);
		}
	}

	/**
	 * 刷新游戏盒子
	 * @param  {Array} data      存放游戏数据的数组
	 * @param  {Array} blocks    存放Div盒子的数组
	 */
	refreshBlocks(data, blocks){
		for(let i=0; i<data.length; i++){
			for(let j=0; j<data[0].length; j++){
				if(data[i][j] == 0){
					blocks[i][j].className = 'none';
				}else if(data[i][j] == 1){
					blocks[i][j].className = 'current';
				}else if(data[i][j] == 2){
					blocks[i][j].className = 'downing';
				}
			}
		}
	}

	/**
	 * 游戏初始化
	 * @param  {Object} dom 包含两个Dom的对象
	 * @return {[type]}     [description]
	 */
	init(dom, type, dir){
		this.gameBox = dom.gameBox;
		this.nextBox = dom.nextBox;
		this.scoreBox = dom.scoreBox;
		this.timeBox = dom.timeBox;
		this.statusBox = dom.statusBox;
		this.next = blockFactory(type, dir);
		this.initBlocks(this.gameBox, this.data, this.gameBlocks);
		this.initBlocks(this.nextBox, this.next.data, this.nextBlocks);
		this.refreshBlocks(this.next.data, this.nextBlocks);
	}

	/**
	 * 设置时间
	 * @param {Number} time 时间s
	 */
	setTime(time){
		this.timeBox.innerHTML = time;
	}

	/**
	 * 设置分数
	 * @param {Number} line 消除的行数
	 */
	setScore(line){
		this.score += line * 10;
		this.scoreBox.innerHTML = this.score;
	}

	/**
	 * 清空gameData中当前方块cur所在位置的数据
	 */
	clearData(){
		for(let i=0; i<this.cur.data.length; i++){
			for(let j=0; j<this.cur.data[0].length; j++){
				if(this.checkPoint(this.cur.origin, i, j)){
					this.data[this.cur.origin.x+i][this.cur.origin.y+j] = 0;
				}
			}
		}
	}

	/**
	 * 设置gameData中当前方块cur所在位置的数据
	 */
	setData(){
		for(let i=0; i<this.cur.data.length; i++){
			for(let j=0; j<this.cur.data[0].length; j++){
				if(this.checkPoint(this.cur.origin, i, j)){
					this.data[this.cur.origin.x+i][this.cur.origin.y+j] = this.cur.data[i][j];
				}
			}
		}
	}

	/**
	 * 检测当前方块的所有点在gameBox容器里面是否合法
	 * @param  {Object} pos {x, y}
	 * @param  {Number} x   向下偏移
	 * @param  {Number} y   向右偏移
	 * @return {Boolean}    true 合法： false非法
	 */
	checkPoint(pos, x, y){
		if(pos.x + x < 0){//高于gameBox上边界
			console.log('上')
			return false;
		}else if(pos.x + x >= this.data.length){//低于下边界
			console.log('下')
			return false;
		}else if(pos.y + y < 0){//小于左边界
			console.log('左')
			return false;
		}else if(pos.y + y >= this.data[0].length){//大于等于又边界
			console.log(pos.y , y+' 右')
			return false;
		}else if(this.data[pos.x + x][pos.y + y] == 1){//已存在方块
			console.log('有')
			return false;
		}
		return true;
	}

	/**
	 * 判断有效方块的合法性（数据不为零）
	 * @param  {Object}  pos  方块的原点坐标（4*4规格的）
	 * @param  {Array}  data 方块的数据
	 * @return {Boolean}      true 合理: false 不合理
	 */
	isValid(pos, data){
		//console.log(data[0].length)
		for(let i=0; i<data.length; i++){
			for(let j=0; j<data[0].length; j++){
				if(data[i][j] != 0){
					if(!this.checkPoint(pos, i, j)){
						return false;
					}
				}
			}
		}
		return true;
	}

	/**
	 * 下移方块
	 * @return {Boolean} true 下落成功: false 下落失败
	 */
	down(){
		if(this.cur.canDown(this.isValid, this)){
			this.clearData();
			this.cur.down();//更新一下方块的原点坐标
			this.setData();
			this.refreshBlocks(this.data, this.gameBlocks);
			return true;
		}
		return false;
	}

	/**
	 * 左移方块
	 * @return {[type]} [description]
	 */
	left(){
		if(this.cur.canLeft(this.isValid, this)){
			this.clearData();
			this.cur.left();//更新一下方块的原点坐标
			this.setData();
			this.refreshBlocks(this.data, this.gameBlocks);
		}
	}

	/**
	 * 右移方块
	 * @return {[type]} [description]
	 */
	right(){
		if(this.cur.canRight(this.isValid, this)){
			this.clearData();
			this.cur.right();//更新一下方块的原点坐标
			this.setData();
			this.refreshBlocks(this.data, this.gameBlocks);
		}
	}

	/**
	 * 下坠方块
	 * @return {[type]} [description]
	 */
	fall(){
		while(this.down());
	}

	/**
	 * 旋转方块
	 * @return {[type]} [description]
	 */
	rotate(){
		if(this.cur.canRotate(this.isValid, this)){
			this.clearData();
			this.cur.rotate();//更新一下方块的原点坐标
			this.setData();
			this.refreshBlocks(this.data, this.gameBlocks);
		}
	}

	/**
	 * 固定方块
	 * @return {[type]} [description]
	 */
	fixed(){
		for(let i=0; i<this.cur.data.length; i++){
			for(let j=0; j<this.cur.data[0].length; j++){
				if(this.cur.data[i][j] == 2){
					let x = this.cur.origin.x;
					let y = this.cur.origin.y;
					this.data[x+i][y+j] = 1;
				}
			}
		}
		this.refreshBlocks(this.data, this.gameBlocks);
	}

	/**
	 * 下一个方块
	 * @param  {Number} type 指定方块种类
	 * @param  {Number} dir  指定旋转的类型
	 */
	nextPerform(type, dir){
		this.cur = this.next;
		this.setData();
		this.next = blockFactory(type, dir);
		this.refreshBlocks(this.data, this.gameBlocks);
		this.refreshBlocks(this.next.data, this.nextBlocks);
	}

	/**
	 * 销行
	 * @return {Number} line 消除行数
	 */
	checkClear(){
		let line = 0;
		for(let i=this.data.length-1; i>=0; i--){
			let clearTemp = true;
			for(let j=0; j<this.data[0].length; j++){
				if(this.data[i][j] != 1){
					clearTemp = false;
					break;
				}
			}
			//销行
			if(clearTemp){
				line++;
				for(let m=i; m>0; m--){
					for(let n=0; n<this.data[0].length; n++){
						this.data[m][n] = this.data[m-1][n];
					}
				}
				for(let n=0; n<this.data[0].length; n++){
					this.data[0][n] = 0;
				}
				i++;
			}
		}
		return line;
	}

	/**
	 * 检查游戏结束
	 * 检查第
	 * @return {Boolean} true 游戏结束: false 游戏继续
	 */
	checkOver(){
		let overTemp = false;
		for(let i=3; i<6; i++){
			if(this.data[1][i] == 1){
				overTemp = true;
				break;
			}
		}
		return overTemp;
	}

	/**
	 * 输出游戏结果
	 * @param  {Boolean} win 输赢标志
	 */
	result(win){
		if(win){
			this.statusBox.innerHTML = '您赢了！';
		}else{
			this.statusBox.innerHTML = '您输了！';
		}
	}

	/**
	 * 增加干扰行
	 * @param {Array} lines 0 1二维数组
	 */
	addLines(lines){
		for(let i=0; i<this.data.length-lines.length; i++){
			// 上移lines行
			this.data[i] = this.data[i+lines.length];
		}
		for(let i=0; i<lines.length; i++){
			// 填充
			this.data[this.data.length-lines.length+i] = lines[i];
		}
		this.cur.origin.x -= lines.length;
		if(this.cur.origin.x < 0){
			this.cur.origin.x = 0;
		}
		this.refreshBlocks(this.data, this.gameBlocks);
	}
}


export {Game};